package com.boot.dog.web.security;

import com.boot.dog.web.security.filter.JWTAuthenticationFilter;
import com.boot.dog.web.security.filter.SecurityInterceptorFilter;
import com.boot.dog.web.security.filter.ValidateCodeFilter;
import com.boot.dog.web.security.service.UserDetailsServiceImpl;
import com.boot.dog.web.security.handler.AuthenticationFailHandler;
import com.boot.dog.web.security.handler.MyAccessDeniedHandler;
import com.boot.dog.web.security.handler.MyLogoutSuccessHandler;
import lombok.AllArgsConstructor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Author: MaxLv
 * @Date: 2019/12/2
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@AllArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final AuthenticationSuccessHandler authSuccessHandler;

    private final AuthenticationFailHandler authFailHandler;

    private final MyLogoutSuccessHandler logoutSuccessHandler;

    private final MyAccessDeniedHandler accessDeniedHandler;

    private final SecurityInterceptorFilter securityInterceptorFilter;

    private final ValidateCodeFilter validateCodeFilter;

    private final UserDetailsServiceImpl userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
                .authorizeRequests();
        //registry.antMatchers("/core/common/validateCode").permitAll();
        registry.antMatchers("/core/common/**").permitAll();
        registry.antMatchers("core/test/**");
        registry.and().addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class).formLogin().loginPage("/security/needLogin")
                .loginProcessingUrl("/login").permitAll()
                .successHandler(authSuccessHandler)
                .failureHandler(authFailHandler).and()
                .headers().frameOptions().disable().and()
                .logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler).permitAll().and()
                .authorizeRequests().anyRequest().authenticated().and()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler).and().addFilter(securityInterceptorFilter)
                .addFilter(new JWTAuthenticationFilter(authenticationManager()));
    }

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/v2/api-docs")
                .antMatchers("/swagger-resources/**").antMatchers("/swagger-ui.html").antMatchers("/configuration/**")
                .antMatchers("/webjars/**").antMatchers("/public").antMatchers("/h2-console/**/**");
    }

}
